import sys
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QPushButton, QFileDialog, QMessageBox, QListWidget, QProgressDialog
from PyQt5.QtCore import Qt, pyqtSlot
import pandas as pd
import os
import time

class MainWindow(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        self.setWindowTitle("Excel文件合并工具")
        self.setGeometry(100, 100, 400, 300)

        self.layout = QVBoxLayout()

        # 添加选择Excel文件按钮
        self.select_file_button = QPushButton("选择Excel文件")
        self.select_file_button.clicked.connect(self.select_files)
        self.layout.addWidget(self.select_file_button)

        # 添加显示已选择文件的列表框
        self.selected_files_display = QListWidget()
        self.layout.addWidget(self.selected_files_display)

        # 添加取消选择文件按钮
        self.remove_file_button = QPushButton("取消选择文件")
        self.remove_file_button.clicked.connect(self.remove_selected_file)
        self.layout.addWidget(self.remove_file_button)

        # 添加清空所有文件按钮
        self.clear_all_button = QPushButton("清空所有文件")
        self.clear_all_button.clicked.connect(self.clear_all_files)
        self.layout.addWidget(self.clear_all_button)

        # 添加合并文件按钮
        self.merge_button = QPushButton("合并文件")
        self.merge_button.clicked.connect(self.merge_files)
        self.layout.addWidget(self.merge_button)

        self.setLayout(self.layout)

        # 初始化文件列表
        self.file_paths = []

    def select_files(self):
        file_paths, _ = QFileDialog.getOpenFileNames(self, "选择Excel文件", "", "Excel文件 (*.xlsx)")
        if file_paths:
            new_files = [file for file in file_paths if file not in self.file_paths]
            self.file_paths.extend(new_files)
            self.update_selected_files_display()
            QMessageBox.information(self, "成功", f"选择了 {len(new_files)} 个新文件，总共有 {len(self.file_paths)} 个文件")

    def update_selected_files_display(self):
        self.selected_files_display.clear()
        for file_path in self.file_paths:
            self.selected_files_display.addItem(os.path.basename(file_path))

    def remove_selected_file(self):
        selected_items = self.selected_files_display.selectedItems()
        if selected_items:
            for item in selected_items:
                file_name = item.text()
                for file_path in self.file_paths:
                    if os.path.basename(file_path) == file_name:
                        self.file_paths.remove(file_path)
                        break
                self.selected_files_display.takeItem(self.selected_files_display.row(item))
            QMessageBox.information(self, "成功", f"已取消选择文件: {', '.join([item.text() for item in selected_items])}")
        else:
            QMessageBox.warning(self, "警告", "请选择一个文件以取消选择")

    def clear_all_files(self):
        self.file_paths = []
        self.update_selected_files_display()
        QMessageBox.information(self, "成功", "已清空所有文件")

    @pyqtSlot()
    def merge_files(self):
        if not self.file_paths:
            QMessageBox.warning(self, "警告", "请选择要合并的Excel文件")
            return

        # 显示进度条
        progress_dialog = QProgressDialog("正在合并文件...", "取消", 0, len(self.file_paths), self)
        progress_dialog.setWindowTitle("合并文件")
        progress_dialog.setWindowModality(Qt.WindowModal)
        progress_dialog.setMinimumWidth(300)  # 设置最小宽度
        progress_dialog.show()

        try:
            # 读取所有文件的第一个sheet
            dfs = []
            for i, file_path in enumerate(self.file_paths):
                if progress_dialog.wasCanceled():
                    QMessageBox.warning(self, "警告", "合并操作已取消")
                    return
                try:
                    print(f"读取文件: {file_path}")
                    df = pd.read_excel(file_path)
                    dfs.append(df)
                except Exception as e:
                    QMessageBox.critical(self, "错误", f"读取文件 {file_path} 时发生错误: {str(e)}")
                    return
                progress_dialog.setValue(i + 1)
                QApplication.processEvents()  # 确保进度条更新

            if not dfs:
                QMessageBox.warning(self, "警告", "没有成功读取任何文件")
                return

            merged_df = pd.concat(dfs, ignore_index=True)

            # 保存合并后的文件
            save_path, _ = QFileDialog.getSaveFileName(self, "保存合并后的Excel文件", "", "Excel文件 (*.xlsx)")
            if save_path:
                # 显示保存进度条
                save_progress_dialog = QProgressDialog("正在保存文件...", "取消", 0, 100, self)
                save_progress_dialog.setWindowTitle("保存文件")
                save_progress_dialog.setWindowModality(Qt.WindowModal)
                save_progress_dialog.setMinimumWidth(300)  # 设置最小宽度
                save_progress_dialog.show()

                try:
                    print(f"保存文件: {save_path}")
                    merged_df.to_excel(save_path, index=False)
                    for i in range(101):
                        if save_progress_dialog.wasCanceled():
                            QMessageBox.warning(self, "警告", "保存操作已取消")
                            return
                        save_progress_dialog.setValue(i)
                        time.sleep(0.01)  # 模拟保存时间
                        QApplication.processEvents()  # 确保进度条更新
                    QMessageBox.information(self, "成功", f"文件已合并并保存到 {save_path}")
                except Exception as e:
                    QMessageBox.critical(self, "错误", f"保存文件时发生错误: {str(e)}")
        except Exception as e:
            QMessageBox.critical(self, "错误", f"合并文件时发生错误: {str(e)}")
        finally:
            progress_dialog.close()
            save_progress_dialog.close()

if __name__ == "__main__":
    app = QApplication(sys.argv)
    mainWindow = MainWindow()
    mainWindow.show()
    sys.exit(app.exec_())
